package com.carter.springframework.core.annotation;

import com.carter.springframework.beans.exception.BeanException;
import com.carter.springframework.util.ObjectUtils;
import com.carter.springframework.util.ReflectionUtils;
import com.carter.springframework.util.StringUtils;
import com.sun.istack.internal.Nullable;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

final class AnnotationTypeMapping {
    private static final MirrorSets.MirrorSet[] EMPTY_MIRROR_SETS = new MirrorSets.MirrorSet[0];

    //源注解，即当前注解为元注解时，当前注解标注的注解
    @Nullable
    private final AnnotationTypeMapping source;

    //根注解，即当前注解为元注解时，注解层次结构中的顶层注解
    private final AnnotationTypeMapping root;

    //注解距离根注解的距离，如果当前注解为根注解则为0
    private final int distance;

    //当前注解的类型
    private final Class<? extends Annotation> annotationType;

    //根注解到当前注解的列表
    private final List<Class<? extends Annotation>> metaTypes;

    //注解实例
    @Nullable
    private final Annotation annotation;

    //注解的属性方法
    private final AttributeMethods attributes;

    //注解中属性方法的镜像集合
    private final MirrorSets mirrorSets;

    //当前attribute下标-> root attributes下标(是当前attributes下标的别名方法下标)
    private final int[] aliasMappings;

    //当前 attributes下标(或其别名下标) -> root attributes 同名属性方法的下标
    private final int[] conventionMappings;

    //attributes下标 ->对应的(同名或别名)较高层次的AnnotationTypeMapping的attributes下标
    private final int[] annotationValueMappings;

    //attributes下标 -> 对应的(同名或别名)较高层次的AnnotationTypeMapping
    private final AnnotationTypeMapping[] annotationValueSource;

    //注解属性方法-> 使用@AliasFor标注了该注解属性方法名称的注解属性列表
    private final Map<Method, List<Method>> aliasedBy;

    //当前注解的属性值是否是合成的
    private final boolean synthesizable;

    //当前注解所有属性方法及其别名方法
    private final Set<Method> claimedAliases = new HashSet<>();


    AnnotationTypeMapping(@Nullable AnnotationTypeMapping source, Class<? extends Annotation> annotationType, @Nullable Annotation annotation) {
        //声明当前元注解的源注解映射对象
        this.source = source;
        //当前元注解所在树根节点对应的元注解映射对象
        this.root = (source != null ? source.getRoot() : this);
        //与树根节点对应的元注解映射对象的距离
        this.distance = (source == null ? 0 : source.getDistance() + 1);
        //当前元注解的类型
        this.annotationType = annotationType;
        // 记录全部子元注解类型
        this.metaTypes = merge(
                source != null ? source.getMetaTypes() : null,
                annotationType);
        this.annotation = annotation;

        //==========================属性解析=================================
        //将当前元注解的属性解析为AttributeMethods
        this.attributes = AttributeMethods.forAnnotationType(annotationType);
        //属性别名与相关的值缓存
        this.mirrorSets = new MirrorSets();
        this.aliasMappings = filledIntArray(this.attributes.size());
        this.conventionMappings = filledIntArray(this.attributes.size());
        this.annotationValueMappings = filledIntArray(this.attributes.size());
        this.annotationValueSource = new AnnotationTypeMapping[this.attributes.size()];
        this.aliasedBy = resolveAliasedForTargets();
        //初始化别名属性，为所有存在别名的属性建立MirrorSet
        processAliases();
        //为当前注解内互为并名的属性建立属性映射
        addConventionMappings();
        //为跨注解互为别名的属性建立属性映射
        addConventionAnnotationValues();
        this.synthesizable = computeSynthesizableFlag();
    }


    private static <T> List<T> merge(@Nullable List<T> existing, T element) {
        if (existing == null) {
            return Collections.singletonList(element);
        }
        List<T> merged = new ArrayList<>(existing.size() + 1);
        merged.addAll(existing);
        merged.add(element);
        return Collections.unmodifiableList(merged);
    }

    private Map<Method, List<Method>> resolveAliasedForTargets() {
        Map<Method, List<Method>> aliasedBy = new HashMap<>();
        for (int i = 0; i < this.attributes.size(); i++) {
            //遍历当前注解的属性方法，并获取其中的带有@AliasFor的方法
            Method attribute = this.attributes.get(i);
            AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, AliasFor.class);
            if (aliasFor != null) {
                //获取别名指定的注解类中的方法，并建立别名属性->[属性1]的映射集合
                Method target = resolveAliasTarget(attribute, aliasFor);
                aliasedBy.computeIfAbsent(target, key -> new ArrayList<>()).add(attribute);
            }
        }
        return Collections.unmodifiableMap(aliasedBy);
    }

    private Method resolveAliasTarget(Method attribute, AliasFor aliasFor) {
        return resolveAliasTarget(attribute, aliasFor, true);
    }

    private Method resolveAliasTarget(Method attribute, AliasFor aliasFor, boolean checkAliasPair) {
        if (StringUtils.hasText(aliasFor.value()) && StringUtils.hasText(aliasFor.attribute())) {
            throw new BeanException(String.format(
                    "In @AliasFor declared on %s, attribute 'attribute' and its alias 'value' " +
                            "are present with values of '%s' and '%s', but only one is permitted.",
                    AttributeMethods.describe(attribute), aliasFor.attribute(),
                    aliasFor.value()));
        }

        //1、若Annotation指定的是Annotation，则认为目标就是当前注解类
        Class<? extends Annotation> targetAnnotation = aliasFor.annotation();
        if (targetAnnotation == Annotation.class) {
            targetAnnotation = this.annotationType;
        }
        //2、获取aliasFrom#attribute，若为空则再获取aliasFrom#value
        String targetAttributeName = aliasFor.attribute();
        if (!StringUtils.hasLength(targetAttributeName)) {
            targetAttributeName = aliasFor.value();
        }
        if (!StringUtils.hasLength(targetAttributeName)) {
            targetAttributeName = attribute.getName();
        }
        //3、从指定类中获得别名指定指定的注解属性对应的方法
        Method target = AttributeMethods.forAnnotationType(targetAnnotation).get(targetAttributeName);
        if (target == null) {
            //a.校验是否能找到别名方法
            if (targetAnnotation == this.annotationType) {
                throw new BeanException(String.format("@AliasFor declaration on %s declares an alias for '%s' which is not present.",
                        AttributeMethods.describe(attribute), targetAttributeName));
            }
            throw new BeanException(String.format(
                    "%s is declared as an @AliasFor nonexistent %s.",
                    StringUtils.capitalize(AttributeMethods.describe(attribute)),
                    AttributeMethods.describe(targetAnnotation, targetAttributeName)));
        }
        //b.校验别名与原属性对应的方法是否不为一个方法
        if (target.equals(attribute)) {
            throw new BeanException(String.format(
                    "@AliasFor declaration on %s points to itself. " +
                            "Specify 'annotation' to point to a same-named attribute on a meta-annotation.",
                    AttributeMethods.describe(attribute)));
        }
        // c.校验别名与原属性对应的方法返回值是否一致
        if (!isCompatibleReturnType(attribute.getReturnType(), target.getReturnType())) {
            throw new BeanException(String.format(
                    "Misconfigured aliases: %s and %s must declare the same return type.",
                    AttributeMethods.describe(attribute),
                    AttributeMethods.describe(target)));
        }
        // d.若有必要，则再校验声明别名方法的注解是@AliasFor指定的注解类型
        if (isAliasPair(target) && checkAliasPair) {
            AliasFor targetAliasFor = target.getAnnotation(AliasFor.class);
            if (targetAliasFor != null) {
                Method mirror = resolveAliasTarget(target, targetAliasFor, false);
                if (!mirror.equals(attribute)) {
                    throw new BeanException(String.format(
                            "%s must be declared as an @AliasFor %s, not %s.",
                            StringUtils.capitalize(AttributeMethods.describe(target)),
                            AttributeMethods.describe(attribute), AttributeMethods.describe(mirror)));
                }
            }
        }
        return target;
    }


    private boolean isAliasPair(Method target) {
        return (this.annotationType == target.getDeclaringClass());
    }

    private boolean isCompatibleReturnType(Class<?> attributeType, Class<?> targetType) {
        return (attributeType == targetType || attributeType == targetType.getComponentType());
    }

    private void processAliases() {
        List<Method> aliases = new ArrayList<>();
        //遍历当前注解中的属性，处理属性与其相关的别名
        for (int i = 0; i < this.attributes.size(); i++) {
            aliases.clear(); //复用集合避免重复创建
            aliases.add(this.attributes.get(i));
            //1.收集注解
            collectAliases(aliases);
            if (aliases.size() > 1) {
                //2.处理注解
                processAliases(i, aliases);
            }
        }
    }


    private void collectAliases(List<Method> aliases) {
        AnnotationTypeMapping mapping = this;
        while (mapping != null) {
            int size = aliases.size();
            for (int j = 0; j < size; j++) {
                //获取以该属性作为别名的子类属性
                List<Method> additional = mapping.aliasedBy.get(aliases.get(j));
                if (additional != null) {
                    aliases.addAll(additional);
                }
            }
            mapping = mapping.source; //继续向声明当前元注解的子注解递归
        }
    }

    private void processAliases(int attributeIndex, List<Method> aliases) {
        // 确认别名链上，是否有别名字段来自于root
        int rootAttributeIndex = getFirstRootAttributeIndex(aliases);
        AnnotationTypeMapping mapping = this;
        // 从当前注解向root递归
        while (mapping != null) {
            // 若有当前正在处理的注解中：
            // 1.有别名字段来自于root；
            // 2.别名链中有一个别名来自于该注解；
            // 则在当前处理的注解的aliasMappings上，记录这个来自于root的别名属性，表示它存在一个来自root的别名
            if (rootAttributeIndex != -1 && mapping != this.root) {
                for (int i = 0; i < mapping.attributes.size(); i++) {
                    if (aliases.contains(mapping.attributes.get(i))) {
                        mapping.aliasMappings[i] = rootAttributeIndex;
                    }
                }
            }
            //构建MirrorSet，解析别名链上的属性构建映射关系
            mapping.mirrorSets.updateFrom(aliases);
            mapping.claimedAliases.addAll(aliases);
            if (mapping.annotation != null) {
                //根据MirrorSet，从别名链中选择出唯一生效的属性作为它们的最终实际属性
                int[] resolvedMirrors = mapping.mirrorSets.resolve(null, mapping.annotation, ReflectionUtils::invokeMethod);
                //遍历当前正在处理的注解的全部属性
                for (int i = 0; i < mapping.attributes.size(); i++) {
                    //若该属性在别名链中存在
                    if (aliases.contains(mapping.attributes.get(i))) {
                        //在分别记录该属性的一些信息：
                        //1.记录该属性应当从哪个注解中取值
                        this.annotationValueSource[attributeIndex] = mapping;
                        //2.记录该属性应当从那个注解的那个属性中取值
                        this.annotationValueMappings[attributeIndex] = resolvedMirrors[i];
                    }
                }
            }

            mapping = mapping.source;
        }
    }


    private int getFirstRootAttributeIndex(Collection<Method> aliases) {
        AttributeMethods rootAttributes = this.root.getAttributes();
        for (int i = 0; i < rootAttributes.size(); i++) {
            if (aliases.contains(rootAttributes.get(i))) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 用于实现根注解覆盖所有其元注解中同名同类型属性
     */
    private void addConventionMappings() {
        if (this.distance == 0) {
            return;
        }
        AttributeMethods rootAttributes = this.root.getAttributes();
        int[] mappings = this.conventionMappings;
        for (int i = 0; i < mappings.length; i++) {
            //遍历当前注解的属性，判断是否在根注解存在
            String name = this.attributes.get(i).getName();
            int mapped = rootAttributes.indexOf(name);

            //若存在，并且该属性不为“value”
            MirrorSets.MirrorSet mirrors = getMirrorSets().getAssigned(i);
            if (!MergedAnnotation.VALUE.equals(name) && mapped != -1) {
                mappings[i] = mapped;
                //若该属性还有别名，则让该属性和全部别名属性都从根注解取值
                if (mirrors != null) {
                    for (int j = 0; j < mirrors.size(); j++) {
                        mappings[mirrors.getAttributeIndex(j)] = mapped;
                    }
                }
            }
        }
    }

    /**
     * 用于实现子注解覆盖父注解中同名同类型属性的逻辑
     */
    private void addConventionAnnotationValues() {
        //遍历当前注解的全部属性
        for (int i = 0; i < this.attributes.size(); i++) {
            Method attribute = this.attributes.get(i);
            boolean isValueAttribute = MergedAnnotation.VALUE.equals(attribute.getName());
            AnnotationTypeMapping mapping = this;
            //从当前注解向非根注解的子注解递归
            while (mapping != null && mapping.distance > 0) {
                //若当前方法在子注解中存在，则将annotationValueMappings和annotationValueSource替换为该子注解和子注解的属性
                //由于替换前会比较annotationValueSource中注解距离根注解的距离，
                //所以之前设置的根注解属性不受影响，因为跟注解距离为0，优先级总是最高的
                int mapped = mapping.getAttributes().indexOf(attribute.getName());
                if (mapped != -1 && isBetterConventionAnnotationValue(i, isValueAttribute, mapping)) {
                    this.annotationValueMappings[i] = mapped;
                    this.annotationValueSource[i] = mapping;
                }
                mapping = mapping.source;
            }
        }
    }

    private boolean isBetterConventionAnnotationValue(int index, boolean isValueAttribute, AnnotationTypeMapping mapping) {
        if (this.annotationValueMappings[index] == -1) {
            return true;
        }
        int existingDistance = this.annotationValueSource[index].distance;
        return !isValueAttribute && existingDistance > mapping.distance;
    }

    @SuppressWarnings("unchecked")
    private boolean computeSynthesizableFlag() {
        // Uses @AliasFor for local aliases?
        for (int index : this.aliasMappings) {
            if (index != -1) {
                return true;
            }
        }

        // Uses @AliasFor for attribute overrides in meta-annotations?
        if (!this.aliasedBy.isEmpty()) {
            return true;
        }

        // Uses convention-based attribute overrides in meta-annotations?
        for (int index : this.conventionMappings) {
            if (index != -1) {
                return true;
            }
        }

        // Has nested annotations or arrays of annotations that are synthesizable?
        if (getAttributes().hasNestedAnnotation()) {
            AttributeMethods attributeMethods = getAttributes();
            for (int i = 0; i < attributeMethods.size(); i++) {
                Method method = attributeMethods.get(i);
                Class<?> type = method.getReturnType();
                if (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation())) {
                    Class<? extends Annotation> annotationType =
                            (Class<? extends Annotation>) (type.isAnnotation() ? type : type.getComponentType());
                    AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
                    if (mapping.isSynthesizable()) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Method called after all mappings have been set. At this point no further
     * lookups from child mappings will occur.
     */
    void afterAllMappingsSet() {
        validateAllAliasesClaimed();
        for (int i = 0; i < this.mirrorSets.size(); i++) {
            validateMirrorSet(this.mirrorSets.get(i));
        }
        this.claimedAliases.clear();
    }

    private void validateAllAliasesClaimed() {
        for (int i = 0; i < this.attributes.size(); i++) {
            Method attribute = this.attributes.get(i);
            AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, AliasFor.class);
            if (aliasFor != null && !this.claimedAliases.contains(attribute)) {
                Method target = resolveAliasTarget(attribute, aliasFor);
                throw new BeanException("error");
            }
        }
    }

    private void validateMirrorSet(MirrorSets.MirrorSet mirrorSet) {
        Method firstAttribute = mirrorSet.get(0);
        Object firstDefaultValue = firstAttribute.getDefaultValue();
        for (int i = 1; i <= mirrorSet.size() - 1; i++) {
            Method mirrorAttribute = mirrorSet.get(i);
            Object mirrorDefaultValue = mirrorAttribute.getDefaultValue();
            if (firstDefaultValue == null || mirrorDefaultValue == null) {
                throw new BeanException("error");
            }
            if (!ObjectUtils.nullSafeEquals(firstDefaultValue, mirrorDefaultValue)) {
                throw new BeanException("error");
            }
        }
    }

    /**
     * Get the root mapping.
     *
     * @return the root mapping
     */
    AnnotationTypeMapping getRoot() {
        return this.root;
    }

    /**
     * Get the source of the mapping or {@code null}.
     *
     * @return the source of the mapping
     */
    @Nullable
    AnnotationTypeMapping getSource() {
        return this.source;
    }

    /**
     * Get the distance of this mapping.
     *
     * @return the distance of the mapping
     */
    int getDistance() {
        return this.distance;
    }

    /**
     * Get the type of the mapped annotation.
     *
     * @return the annotation type
     */
    Class<? extends Annotation> getAnnotationType() {
        return this.annotationType;
    }

    List<Class<? extends Annotation>> getMetaTypes() {
        return this.metaTypes;
    }

    /**
     * Get the source annotation for this mapping. This will be the
     * meta-annotation, or {@code null} if this is the root mapping.
     *
     * @return the source annotation of the mapping
     */
    @Nullable
    Annotation getAnnotation() {
        return this.annotation;
    }

    /**
     * Get the annotation attributes for the mapping annotation type.
     *
     * @return the attribute methods
     */
    AttributeMethods getAttributes() {
        return this.attributes;
    }


    int getAliasMapping(int attributeIndex) {
        return this.aliasMappings[attributeIndex];
    }


    int getConventionMapping(int attributeIndex) {
        return this.conventionMappings[attributeIndex];
    }


    @Nullable
    Object getMappedAnnotationValue(int attributeIndex, boolean metaAnnotationsOnly) {
        int mappedIndex = this.annotationValueMappings[attributeIndex];
        if (mappedIndex == -1) {
            return null;
        }
        AnnotationTypeMapping source = this.annotationValueSource[attributeIndex];
        if (source == this && metaAnnotationsOnly) {
            return null;
        }
        return ReflectionUtils.invokeMethod(source.attributes.get(mappedIndex), source.annotation);
    }

    /**
     * Determine if the specified value is equivalent to the default value of the
     * attribute at the given index.
     *
     * @param attributeIndex the attribute index of the source attribute
     * @param value          the value to check
     * @param valueExtractor the value extractor used to extract values from any
     *                       nested annotations
     * @return {@code true} if the value is equivalent to the default value
     */
    boolean isEquivalentToDefaultValue(int attributeIndex, Object value, ValueExtractor valueExtractor) {

        Method attribute = this.attributes.get(attributeIndex);
        return isEquivalentToDefaultValue(attribute, value, valueExtractor);
    }

    /**
     * Get the mirror sets for this type mapping.
     *
     * @return the attribute mirror sets
     */
    MirrorSets getMirrorSets() {
        return this.mirrorSets;
    }


    boolean isSynthesizable() {
        return this.synthesizable;
    }


    private static int[] filledIntArray(int size) {
        int[] array = new int[size];
        Arrays.fill(array, -1);
        return array;
    }

    private static boolean isEquivalentToDefaultValue(Method attribute, Object value,
                                                      ValueExtractor valueExtractor) {

        return areEquivalent(attribute.getDefaultValue(), value, valueExtractor);
    }

    private static boolean areEquivalent(@Nullable Object value, @Nullable Object extractedValue, ValueExtractor valueExtractor) {

        if (ObjectUtils.nullSafeEquals(value, extractedValue)) {
            return true;
        }
        if (value instanceof Class && extractedValue instanceof String) {
            return areEquivalent((Class<?>) value, (String) extractedValue);
        }
        if (value instanceof Class[] && extractedValue instanceof String[]) {
            return areEquivalent((Class[]) value, (String[]) extractedValue);
        }
        if (value instanceof Annotation) {
            return areEquivalent((Annotation) value, extractedValue, valueExtractor);
        }
        return false;
    }

    private static boolean areEquivalent(Class<?>[] value, String[] extractedValue) {
        if (value.length != extractedValue.length) {
            return false;
        }
        for (int i = 0; i < value.length; i++) {
            if (!areEquivalent(value[i], extractedValue[i])) {
                return false;
            }
        }
        return true;
    }

    private static boolean areEquivalent(Class<?> value, String extractedValue) {
        return value.getName().equals(extractedValue);
    }

    private static boolean areEquivalent(Annotation annotation, @Nullable Object extractedValue, ValueExtractor valueExtractor) {

        AttributeMethods attributes = AttributeMethods.forAnnotationType(annotation.annotationType());
        for (int i = 0; i < attributes.size(); i++) {
            Method attribute = attributes.get(i);
            Object value1 = ReflectionUtils.invokeMethod(attribute, annotation);
            Object value2;
            if (extractedValue instanceof TypeMappedAnnotation) {
                //value2 = ((TypeMappedAnnotation<?>) extractedValue).getValue(attribute.getName()).orElse(null);
                value2 = null;
            } else {
                value2 = valueExtractor.extract(attribute, extractedValue);
            }
            if (!areEquivalent(value1, value2, valueExtractor)) {
                return false;
            }
        }
        return true;
    }

    /**
     * MirrorSets是AnnotationTypeMapping的内部类，表示镜像属性方法的集合，镜像属性方法是指互为别名的属性方法
     */
    class MirrorSets {
        //assigned的去重版本
        private MirrorSet[] mirrorSets;

        /**
         * attributes下标 -> 属性对应的镜像 如注解A中，属性a和属性b互为别名，属性c和属性d互为别名，
         * 属性e和属性f无别名， 属性a和属性b的镜像都为mirrorSet1,属性c和属性d的镜像都为mirrorSet2，
         * 则assigned的值为[mirrorSet1,mirrorSet1,mirrorSet2,mirrorSet2,null,null]
         */
        private final MirrorSet[] assigned;

        MirrorSets() {
            this.assigned = new MirrorSet[attributes.size()];
            this.mirrorSets = EMPTY_MIRROR_SETS;
        }

        void updateFrom(Collection<Method> aliases) {
            MirrorSet mirrorSet = null;
            int size = 0;
            int last = -1;
            //遍历当前注解的所有属性
            for (int i = 0; i < attributes.size(); i++) {
                Method attribute = attributes.get(i);
                //若有属性在传入的这一组别名中出现
                if (aliases.contains(attribute)) {
                    size++; //计数+1
                    if (size > 1) { //仅有一个别名的时候不创建MirrorSet实例
                        if (mirrorSet == null) {
                            mirrorSet = new MirrorSet();
                            this.assigned[last] = mirrorSet; //当发现第二次在别名组中出现的属性时，为上一次发现的别名属性建立MirrorSet实例
                        }
                        this.assigned[i] = mirrorSet;
                    }
                    last = i; //记录最后出现那个别名数组下标
                }
            }
            if (mirrorSet != null) {
                mirrorSet.update();
                Set<MirrorSet> unique = new LinkedHashSet<>(Arrays.asList(this.assigned));
                unique.remove(null);
                this.mirrorSets = unique.toArray(EMPTY_MIRROR_SETS); //更新mirrorSets数组
            }
        }



        int size() {
            return this.mirrorSets.length;
        }

        MirrorSet get(int index) {
            return this.mirrorSets[index];
        }

        @Nullable
        MirrorSet getAssigned(int attributeIndex) {
            return this.assigned[attributeIndex];
        }

        int[] resolve(@Nullable Object source, @Nullable Object annotation, ValueExtractor valueExtractor) {
            int[] result = new int[attributes.size()];
            for (int i = 0; i < result.length; i++) {
                //默认情况下，每个属性都调用他本身
                result[i] = i;
            }
            for (int i = 0; i < size(); i++) {
                MirrorSet mirrorSet = get(i);
                //如果有MirrorSet，则调用resolve方法获得这一组关联属性中的唯一有效属性的下标
                int resolved = mirrorSet.resolve(source, annotation, valueExtractor);
                //将该下标强制覆盖全部关联的属性
                for (int j = 0; j < mirrorSet.size; j++) {
                    result[mirrorSet.indexes[j]] = resolved;
                }
            }
            return result;
        }

        /**
         * A single set of mirror attributes.
         */
        class MirrorSet {

            //镜像的属性数量
            private int size;

            /**
             * 注解属性互为别名的索引列表 注解A中，属性a和属性b互为别名，属性c和属性d互为别名，属性e和属性f无别名，
             * <p>
             * 当前MirrorSet可表示属性a和属性b的镜像mirrorSet1，取值为[0,1,-1,-1,-1]
             */
            private final int[] indexes = new int[attributes.size()];

            void update() {
                this.size = 0;
                Arrays.fill(this.indexes, -1);
                for (int i = 0; i < MirrorSets.this.assigned.length; i++) {
                    if (MirrorSets.this.assigned[i] == this) {
                        this.indexes[this.size] = i;
                        this.size++;
                    }
                }
            }

            <A> int resolve(@Nullable Object source, @Nullable A annotation, ValueExtractor valueExtractor) {
                int result = -1;
                Object lastValue = null; //最近一个的有效属性值

                //遍历与当前注解属性属性互为别名的全部属性
                for (int i = 0; i < this.size; i++) {
                    // 获取属性值
                    Method attribute = attributes.get(this.indexes[i]);
                    Object value = valueExtractor.extract(attribute, annotation);
                    boolean isDefaultValue = (value == null ||
                            isEquivalentToDefaultValue(attribute, value, valueExtractor));

                    //如果属性值是默认值，或者与最后有效值相同，则记录该属性下标后返回
                    //以此类推，如果一组互为别名的属性全部都是默认值，则前面的属性——即离根注解最近的——的默认值会作为最终有效值
                    if (isDefaultValue || ObjectUtils.nullSafeEquals(lastValue, value)) {
                        if (result == -1) {
                            result = this.indexes[i];
                        }
                        continue;
                    }

                    //如果属性值不是默认值，并且与最近一个的有效属性值不同, 则抛出异常
                    //这里实际要求一组互为别名的属性中，只允许一个属性的值是非默认值
                    if (lastValue != null && !ObjectUtils.nullSafeEquals(lastValue, value)) {
                        String on = (source != null) ? " declared on " + source : "";
                        throw new BeanException(String.format(
                                "Different @AliasFor mirror values for annotation [%s]%s; attribute '%s' " +
                                        "and its alias '%s' are declared with values of [%s] and [%s].",
                                getAnnotationType().getName(), on,
                                attributes.get(result).getName(),
                                attribute.getName(),
                                ObjectUtils.nullSafeToString(lastValue),
                                ObjectUtils.nullSafeToString(value)));
                    }
                    result = this.indexes[i];
                    lastValue = value;
                }
                return result;
            }

            int size() {
                return this.size;
            }

            Method get(int index) {
                int attributeIndex = this.indexes[index];
                return attributes.get(attributeIndex);
            }

            int getAttributeIndex(int index) {
                return this.indexes[index];
            }
        }
    }
}
